import $ from 'jquery'
import { throttle } from '../../util/throttle';
import Dropdown from '../../com/dropdown'
import NavTree from '../../com/nav-tree'
import './api.scss'

const DEFAULT_VERSION = '2.0';
const LOCAL_STORAGE_KEY = 'targetApi';
const PLATFORM_AVAILABILITY = {
    'jvm': '1.0',
    'common': '1.2',
    'js': '1.1',
    'native': '1.3'
  };

const PLATFORM_ENRICH = {
    'jvm': ['JUnit', 'JUnit5', 'testng', 'JRE7', 'JRE8'].map((tag) => tag.toLowerCase())
};

function hideByTags($elements, state, checkTags, cls) {
  $elements.each((ind, element) => {
      const $element = $(element);
      $element.toggleClass(cls ? cls : 'hidden', !checkTags($element));
  });
}

function getMinVersion(a, b) {
  if (a > b) return b;
  return a;
}

function getTagPlatformName($tagElement) {
    return $tagElement
        .attr("class")
        .split(' ')
        .find((cls) => cls.startsWith('tag-value-'))
        .replace('tag-value-', '')
        .toLowerCase()
}

function updateState(state) {
  localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(state));


  const stateVersion = state.version ? state.version : DEFAULT_VERSION;
  const statePlatforms =
      state.platform
          .filter((platform) => PLATFORM_AVAILABILITY[platform] <= stateVersion)
          .reduce((acc, platform) => {
              const enrich = PLATFORM_ENRICH[platform];
              if (enrich) {
                  return acc.concat([platform, ...enrich]);
              }
              return acc.concat([platform]);
          }, []);

  for (const platform in PLATFORM_AVAILABILITY) {
    const $toggleElement = $(".toggle-platform." + platform);
    $toggleElement.toggleClass("disabled", PLATFORM_AVAILABILITY[platform] > stateVersion)
  }
  const minVersion = statePlatforms.map((platform) => PLATFORM_AVAILABILITY[platform]).reduce(getMinVersion, '1.0');


  hideByTags($('[data-platform]'), state, ($element) => {
    const versions = $element.attr('data-kotlin-version')
        .toLowerCase()
        .split(", ");
    return $element.attr('data-platform')
        .toLowerCase()
        .split(", ")
        .filter((tag, index) => versions[index] <= stateVersion)
        .some((tag) => statePlatforms.includes(tag))
  });
  hideByTags($('.tags__tag.platform'), state, ($element) => {
    if ($element.attr('data-tag-version') > stateVersion) return false;

    return statePlatforms.includes(getTagPlatformName($element))
  });



  $(".tags").each(
    (index, element) => {

      const $element = $(element);
      const activeVersions =
          $.map($element.find(".tags__tag:not(.hidden-version)"), (versionContainer) => $(versionContainer).attr('data-tag-version'));
      if (activeVersions.length === 0) return;
      const minVersion = activeVersions.reduce(getMinVersion);

      $element.children(".kotlin-version").text(minVersion);
    }
  );

  hideByTags($('.tags__tag.kotlin-version'), state, ($element) => $element.text() > minVersion, 'hidden-version');
}

function addSelectToPanel(panelElement, title, config) {
  const selectElement = $(`<div class="api-panel__select"><span class="api-panel__dropdown-title">${title}</span></div>`);
  $(panelElement).append(selectElement);
  new Dropdown(selectElement, config);
}

function addPlatformSelectToPanel(panelElement, config) {
  const selectElement = $(`<div class="api-panel_toggle"></div>`);
  $.each(config.items, (value, item) => {
    const itemElement = $(`<div class="toggle-platform ${value} ${item}"><span>`+item+`</span></div>`);
    selectElement.append(itemElement);
    if (!config.selected.includes(value)) {
      itemElement.addClass('off');
    }
    itemElement.click(() => {
      if (itemElement.hasClass('disabled')) return;
      itemElement.toggleClass('off');
      itemElement.addClass("pressed")
          .delay(200)
          .queue((next) => {
            itemElement.removeClass("pressed");
            next()
          });
      config.onSelect(value);
    });
  });
  $(panelElement).append(selectElement);

}

function fixPlatformsAvailability() {

    // TODO: This is hack to fix broken tag versions generated by Dokka :(
    $('.tags__tag.platform').each((index, element) => {
      const $element = $(element);
      const platformName = getTagPlatformName($element);
      const availability = PLATFORM_AVAILABILITY[platformName];
      if ($element.attr('data-tag-version') < availability) {
          $element.attr('data-tag-version', availability)
      }
    });
}

function initializeSelects() {
  const $breadcrumbs = $('.api-docs-breadcrumbs');
  if ($breadcrumbs.length > 0) {
    $breadcrumbs
      .wrap('<div class="api-page-panel"></div>')
      .before('<div class="api-panel__switchers"></div>');
  } else {
    $('.page-content').prepend('<div class="api-page-panel"><div class="api-panel__switchers"></div><div class="api-docs-breadcrumbs"></div></div>');
  }

  const switchersPanel = $('.api-panel__switchers')[0];

  const state = localStorage.getItem(LOCAL_STORAGE_KEY) ?
    JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) :
    {
      platform: 'all'
    };
  if (state.platform === 'all') {
    state.platform = ['common', 'jvm', 'js', 'native'];
  }
  if ((typeof state.platform) === 'string') {
      state.platform = [state.platform];
  }

  addPlatformSelectToPanel(switchersPanel, {
    items: {
      'common': 'Common',
      'jvm': 'JVM',
      'js': 'JS',
      'native': 'Native'
    },
    selected: state.platform,
    onSelect: (platform) => {
      const index = state.platform.indexOf(platform);
      if (index !== -1) {
        state.platform.splice(index, 1);
      } else {
        state.platform.push(platform);
      }

      updateState(state);
    }
  });


  addSelectToPanel(switchersPanel, "Version", {
    items: {
      '1.0': '1.0',
      '1.1': '1.1',
      '1.2': '1.2',
      '1.3': '1.3',
      '1.4': '1.4',
      '1.5': '1.5',
      '1.6': '1.6',
      '1.7': '1.7',
      '1.8': '1.8',
      '1.9': '1.9',
      '2.0': '2.0'
    },
    selected: state.version != null ? state.version : DEFAULT_VERSION,
    onSelect: (version) => {
      if(version !== DEFAULT_VERSION){
        state.version = version;
      } else {
        delete state.version;
      }

      updateState(state)
    }
  });

  updateState(state);
}

function initializeSections() {
    $(".declarations").click(event => {
        event.preventDefault();
        const url = $(event.currentTarget).find("a:first").attr("href");
        window.open(url, event.ctrlKey || event.metaKey? '_blank' : '_self');
    });
}

function handleApiPageScroll() {
    // Container with float buttons should render after 800px
    const scrollOffset = 800;
    const $scrollTopButton = $('.scroll-button-top');
    const $buttonsBox = $('.api-layout_button-box');

    if (document.body.scrollTop > scrollOffset || document.documentElement.scrollTop > scrollOffset) {
        $buttonsBox.addClass('api-layout_button-box_visible')
    } else {
        $buttonsBox.removeClass('api-layout_button-box_visible')
    }

    $scrollTopButton.on('click', function () {
        window.scroll({
            top: 0,
            left: 0,
            behavior: 'smooth'
        });
    });
}

$(document).ready(() => {
  fixPlatformsAvailability();
  initializeSelects();
  initializeSections();
  handleApiPageScroll();
  new NavTree(document.querySelector('.js-side-tree-nav'));
});

window.onscroll = throttle(function() {handleApiPageScroll()}, 250);
